/*
 * Copyright 2002-2021 the original author or authors.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      https://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package org.springframework.aop.framework;

import java.io.Serializable;
import java.lang.reflect.Proxy;

import org.springframework.aop.SpringProxy;
import org.springframework.core.NativeDetector;

/**
 * Default {@link AopProxyFactory} implementation, creating either a CGLIB proxy
 * or a JDK dynamic proxy.
 *
 * <p>Creates a CGLIB proxy if one the following is true for a given
 * {@link AdvisedSupport} instance:
 * <ul>
 * <li>the {@code optimize} flag is set
 * <li>the {@code proxyTargetClass} flag is set
 * <li>no proxy interfaces have been specified
 * </ul>
 *
 * <p>In general, specify {@code proxyTargetClass} to enforce a CGLIB proxy,
 * or specify one or more interfaces to use a JDK dynamic proxy.
 *
 * @author Rod Johnson
 * @author Juergen Hoeller
 * @author Sebastien Deleuze
 * @see AdvisedSupport#setOptimize
 * @see AdvisedSupport#setProxyTargetClass
 * @see AdvisedSupport#setInterfaces
 * @since 12.03.2004
 */
@SuppressWarnings("serial")
public class DefaultAopProxyFactory implements AopProxyFactory, Serializable {


	@Override
	public AopProxy createAopProxy(AdvisedSupport config) throws AopConfigException {
		/**
		 * config指的是我们在外面创建的ProxyFactory对象
		 * NativeDetector.inNativeImage()：当前Spring项目是不是在GraalVM虚拟机上运行的，如果是则使用JDK动态代理创建代理对象
		 * config.isOptimize()：如果isOptimize为true，则会使用cglib动态代理创建代理对象，因为Spring认为cglib比jdk动态代理要快
		 * config.isProxyTargetClass()：要代理的是不是一个类，如果为true则使用cglib动态代理创建代理对象
		 * hasNoUserSuppliedProxyInterfaces(config)：当前ProxyFactory对象有没有去添加接口（addInterface），
		 * 如果添加了则返回false并使用JDK动态代理创建代理对象，如果没有添加则返回true并使用cglib动态代理创建代理对象
		 */
		if (!NativeDetector.inNativeImage() &&
				/**
				 * 类似于：
				 * ProxyFactory proxyFactory = new ProxyFactory();
				 * proxyFactory.setOptimize(true);
				 * proxyFactory.setProxyTargetClass(true);
				 * 如果添加了proxyFactory.addInterface();
				 * 那么hasNoUserSuppliedProxyInterfaces(config)为false，如果没有添加则为true
				 */
				(config.isOptimize() || config.isProxyTargetClass() || hasNoUserSuppliedProxyInterfaces(config))) {

			// 获取被代理类的类型
			Class<?> targetClass = config.getTargetClass();
			if (targetClass == null) {
				throw new AopConfigException("TargetSource cannot determine target class: " +
						"Either an interface or a target is required for proxy creation.");
			}
			/**
			 * targetClass.isInterface()：如果被代理的类是一个接口
			 * 举个例子：
			 * ProxyFactory proxyFactory = new ProxyFactory();
			 * proxyFactory.setTargetClass(UserInterface.class);
			 * 这样的话就表示被代理类是一个接口
			 * Proxy.isProxyClass(targetClass)：当前所设置的被代理类是不是已经进行过JDK动态代理而生成的代理类
			 */
			if (targetClass.isInterface() || Proxy.isProxyClass(targetClass)) {
				/**
				 * 使用jdk动态代理创建代理对象
				 */
				return new JdkDynamicAopProxy(config);
			}
			/**
			 * 返回Cglib创建的代理对象
			 */
			return new ObjenesisCglibAopProxy(config);
		} else {
			/**
			 * 使用jdk动态代理创建代理对象
			 */
			return new JdkDynamicAopProxy(config);
		}
	}

	/**
	 * Determine whether the supplied {@link AdvisedSupport} has only the
	 * {@link org.springframework.aop.SpringProxy} interface specified
	 * (or no proxy interfaces specified at all).
	 */
	private boolean hasNoUserSuppliedProxyInterfaces(AdvisedSupport config) {
		Class<?>[] ifcs = config.getProxiedInterfaces();
		return (ifcs.length == 0 || (ifcs.length == 1 && SpringProxy.class.isAssignableFrom(ifcs[0])));
	}

}
